package org.dromara.tearoom.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.tearoom.domain.GeeOpenDevice;
import org.dromara.tearoom.domain.TerIotDevice;
import org.dromara.tearoom.domain.bo.TerIotDeviceBo;
import org.dromara.tearoom.domain.enums.IotDeviceStateEnum;
import org.dromara.tearoom.domain.vo.TerIotDeviceVo;
import org.dromara.tearoom.mapper.TerIotDeviceMapper;
import org.dromara.tearoom.service.IGeeOpenService;
import org.dromara.tearoom.service.ITerIotDeviceService;
import org.dromara.tearoom.util.MqttUtil;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * IoT设备Service业务层处理
 *
 * @author LionLi
 * @date 2025-04-08
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class TerIotDeviceServiceImpl implements ITerIotDeviceService {

    private final TerIotDeviceMapper baseMapper;
    private final IGeeOpenService geeOpenService;

    /**
     * 查询IoT设备
     *
     * @param id 主键
     * @return IoT设备
     */
    @Override
    public TerIotDeviceVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询IoT设备列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return IoT设备分页列表
     */
    @Override
    public TableDataInfo<TerIotDeviceVo> queryPageList(TerIotDeviceBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<TerIotDevice> lqw = buildQueryWrapper(bo);
        Page<TerIotDeviceVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的IoT设备列表
     *
     * @param bo 查询条件
     * @return IoT设备列表
     */
    @Override
    public List<TerIotDeviceVo> queryList(TerIotDeviceBo bo) {
        LambdaQueryWrapper<TerIotDevice> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TerIotDevice> buildQueryWrapper(TerIotDeviceBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TerIotDevice> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(TerIotDevice::getId);
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceKey()), TerIotDevice::getDeviceKey, bo.getDeviceKey());
        lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), TerIotDevice::getDeviceName, bo.getDeviceName());
        lqw.like(StringUtils.isNotBlank(bo.getNickname()), TerIotDevice::getNickname, bo.getNickname());
        lqw.eq(StringUtils.isNotBlank(bo.getSerialNumber()), TerIotDevice::getSerialNumber, bo.getSerialNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getPicUrl()), TerIotDevice::getPicUrl, bo.getPicUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getGroupIds()), TerIotDevice::getGroupIds, bo.getGroupIds());
        lqw.eq(bo.getRoomId() != null, TerIotDevice::getRoomId, bo.getRoomId());
        lqw.eq(StringUtils.isNotBlank(bo.getProductKey()), TerIotDevice::getProductKey, bo.getProductKey());
        lqw.eq(bo.getDeviceType() != null, TerIotDevice::getDeviceType, bo.getDeviceType());
        lqw.eq(bo.getGatewayId() != null, TerIotDevice::getGatewayId, bo.getGatewayId());
        lqw.eq(bo.getState() != null, TerIotDevice::getState, bo.getState());
        lqw.eq(bo.getOnlineTime() != null, TerIotDevice::getOnlineTime, bo.getOnlineTime());
        lqw.eq(bo.getOfflineTime() != null, TerIotDevice::getOfflineTime, bo.getOfflineTime());
        lqw.eq(bo.getActiveTime() != null, TerIotDevice::getActiveTime, bo.getActiveTime());
        lqw.eq(StringUtils.isNotBlank(bo.getIp()), TerIotDevice::getIp, bo.getIp());
        lqw.eq(StringUtils.isNotBlank(bo.getFirmwareId()), TerIotDevice::getFirmwareId, bo.getFirmwareId());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceSecret()), TerIotDevice::getDeviceSecret, bo.getDeviceSecret());
        lqw.eq(StringUtils.isNotBlank(bo.getMqttClientId()), TerIotDevice::getMqttClientId, bo.getMqttClientId());
        lqw.like(StringUtils.isNotBlank(bo.getMqttUsername()), TerIotDevice::getMqttUsername, bo.getMqttUsername());
        lqw.eq(StringUtils.isNotBlank(bo.getMqttPassword()), TerIotDevice::getMqttPassword, bo.getMqttPassword());
        lqw.eq(StringUtils.isNotBlank(bo.getAuthType()), TerIotDevice::getAuthType, bo.getAuthType());
        lqw.eq(bo.getLatitude() != null, TerIotDevice::getLatitude, bo.getLatitude());
        lqw.eq(bo.getLongitude() != null, TerIotDevice::getLongitude, bo.getLongitude());
        lqw.eq(bo.getAreaId() != null, TerIotDevice::getAreaId, bo.getAreaId());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), TerIotDevice::getAddress, bo.getAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getConfig()), TerIotDevice::getConfig, bo.getConfig());
        return lqw;
    }

    /**
     * 新增IoT设备
     *
     * @param bo IoT设备
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(TerIotDeviceBo bo) {
        TerIotDevice add = MapstructUtils.convert(bo, TerIotDevice.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改IoT设备
     *
     * @param bo IoT设备
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(TerIotDeviceBo bo) {
        TerIotDevice update = MapstructUtils.convert(bo, TerIotDevice.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 修改IoT设备根据设备编号
     *
     * @param device IoT设备
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByDeviceKey(GeeOpenDevice device) {
        LambdaUpdateWrapper<TerIotDevice> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(TerIotDevice::getDeviceKey,device.getMac())
                .set(TerIotDevice::getIp,device.getIp())
                .set(TerIotDevice::getFirmwareId,device.getVersion())
                .set(TerIotDevice::getSsid,device.getSsid())
                .set(TerIotDevice::getKeyStatus,device.getKey())
                .set(TerIotDevice::getWifiLock,device.getWifiLock())
                .set(TerIotDevice::getKeyLock,device.getKeyLock())
                .set(TerIotDevice::getOnlineTime,new Date())
                .set(TerIotDevice::getState, IotDeviceStateEnum.ONLINE.getState());
        return baseMapper.update(wrapper) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TerIotDevice entity){
        MqttUtil.subscribeInit(entity.getMqttPublish());
    }

    /**
     * 校验并批量删除IoT设备信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 修改开关状态
     *
     * @param id    用户ID
     * @param state 状态
     * @return 结果
     */
    @Override
    public int updateDeviceKeyStatus(Long id, Integer state) {
        TerIotDeviceVo deviceVo=baseMapper.selectVoById(id);
        if(ObjectUtil.isEmpty(deviceVo)){
            throw new ServiceException("设备不存在");
        }
        geeOpenService.switchOffByMqtt(deviceVo.getMqttSubscribe(),state);
        return baseMapper.update(null,
                new LambdaUpdateWrapper<TerIotDevice>()
                        .set(TerIotDevice::getKeyStatus, state)
                        .eq(TerIotDevice::getId, id));
    }

    /**
     * 控制某类设备开关
     *
     * @param roomId
     * @param onOff
     * @param deviceClass
     */
    @Override
    public void operateDeviceOnOffByClass(Long roomId, Boolean onOff, Integer deviceClass) {
        TerIotDeviceBo iotDeviceBo=new TerIotDeviceBo();
        iotDeviceBo.setRoomId(roomId);
        iotDeviceBo.setDeviceClass(deviceClass);
        List<TerIotDeviceVo> deviceVoList=this.queryList(iotDeviceBo);
        if(CollUtil.isNotEmpty(deviceVoList)){
            for(TerIotDeviceVo deviceVo:deviceVoList){
                log.info("控制房间ID:{}设备开关为:{}",roomId,onOff ? "开" : "关");
                geeOpenService.switchOffByMqtt(deviceVo.getMqttSubscribe(),onOff ? 1 : 0);
            }
        }
    }

    /**
     * 查询符合条件的IoT设备订阅主题列表
     *
     * @return IoT设备列表
     */
    @Override
    public List<String> getAllMqttPublish() {
        List<TerIotDeviceVo> terIotDeviceVoList=baseMapper.selectVoList();
        List<String> publishList=terIotDeviceVoList.stream().filter(i-> StrUtil.isNotBlank(i.getMqttPublish())).map(TerIotDeviceVo::getMqttPublish).toList();
        return publishList;
    }

    /**
     * 刷新所有设备信息状态
     */
    @Override
    public void refreshAllDeviceInfo() {
        log.info("开始刷新所有设备信息状态");
        List<TerIotDeviceVo> terIotDeviceVoList=baseMapper.selectVoList();
        List<String> subscribeList=terIotDeviceVoList.stream().filter(i-> StrUtil.isNotBlank(i.getMqttSubscribe())).map(TerIotDeviceVo::getMqttSubscribe).toList();
        subscribeList.stream().forEach(item->{
            geeOpenService.getDeviceInfoByMqtt(item);
        });
    }
}
